#pragma once
#include "GameTypes.h"

// 28
class InputEvent
{
public:
    virtual ~InputEvent();

    virtual bool			IsIDEvent();
    virtual BSFixedString	*	GetControlID();

    enum
    {
        kDeviceType_Keyboard = 0,
        kDeviceType_Mouse,
        kDeviceType_Gamepad,
        kDeviceType_Kinect
    };

    enum
    {
        kEventType_Button = 0,
        kEventType_MouseMove,
        kEventType_Char,
        kEventType_Thumbstick,
        kEventType_DeviceConnect,
        kEventType_Kinect,
        kEventType_Unk6
    };

    u64		deviceType;		// 08
    u64		eventType;		// 10
    InputEvent	* next;			// 18
    u32		unk20;			// 20
    u32		handled;		// 24 - When this != 2 it means stop processing
};
static_assert(sizeof(InputEvent) == 0x28);

// 08
class IDEvent
{
public:
    BSFixedString	controlID;	// 00
};

// 40
class ButtonEvent : public IDEvent, public InputEvent
{
public:
    unsigned int			keyMask;	// 30
    unsigned int			flags;		// 34 (00000038 when ALT is pressed, 0000001D when STRG is pressed)
    float			isDown;		// 38
    float			timer;		// 3C 
};
static_assert(sizeof(ButtonEvent) == 0x040);

// 30
class CharacterEvent : public InputEvent
{
public:
    unsigned int keyCode;
};
static_assert(sizeof(CharacterEvent) == 0x030);

// 40
class MouseMoveEvent : public IDEvent
{
public:
    unsigned int unk28[4];
};

// 40
class CursorMoveEvent : public IDEvent, public InputEvent
{
public:
    unsigned int unk28[4];
};

// 48
class ThumbstickEvent : public IDEvent, public InputEvent
{
public:
    u64 stick; // 0xB left 0xC right
    float x;
    float y;
    u32 unk40;
    u32 unk44;
};
static_assert(sizeof(ThumbstickEvent) == 0x048);

// 30
class DeviceConnectEvent : public InputEvent
{
public:
    u64 connected;
};
static_assert(sizeof(DeviceConnectEvent) == 0x030);

// 40
class KinectEvent : public IDEvent, public InputEvent
{
public:
    unsigned int unk28[4];
};
static_assert(sizeof(KinectEvent) == 0x040);

class BSInputEventUser
{
public:
    BSInputEventUser() : enabled(false) { }
    BSInputEventUser(bool bEnabled) : enabled(bEnabled) { }
    virtual ~BSInputEventUser() { };

    virtual bool ShouldHandleEvent(InputEvent * inputEvent = nullptr) { return enabled; };
    virtual void OnKinectEvent(KinectEvent * inputEvent) { };
    virtual void OnDeviceConnectEvent(DeviceConnectEvent * inputEvent) { };
    virtual void OnThumbstickEvent(ThumbstickEvent * inputEvent) { };
    virtual void OnCursorMoveEvent(CursorMoveEvent * inputEvent) { };
    virtual void OnMouseMoveEvent(MouseMoveEvent * inputEvent) { };
    virtual void OnCharacterEvent(CharacterEvent * inputEvent) { };
    virtual void OnButtonEvent(ButtonEvent * inputEvent) { };
    virtual void unk_09();

    bool	enabled;
};

class BSInputEventReceiver
{
public:
    virtual ~BSInputEventReceiver();
    
};

class MenuControls : public BSInputEventReceiver
{
public:
    virtual ~MenuControls() {};

    static MenuControls* GetSingleton()
    {
        RelocPtr<MenuControls*> singleton(0x058F6DD8);
        return *singleton;
    }

    u64	unk10;	// 10
    u64	unk18;	// 18
    BSTArray<BSInputEventUser*>	inputEvents;	// 18
    //BSInputEventUser			* events[8];	// 30
};
static_assert(sizeof(MenuControls) == 0x28);